DrawBoard();
DrawScrambleButton();
ScrambleBoard();
FillBoard();
FillSquare();
ProcessPress();
MoveTile();
CheckSolved();
IntToString();
DigitToChar();

boardValues;

EXPORT Slider()
//Slider v1.0
//2022
//Tony Gallo
//tgallo@tbaytel.com
//http://my.tbaytel.net/tgallo/hp prime

BEGIN
local touch;
LOCAL X,Y;
local done;
local key;
local i,j,indx;


//title screen
RECT_P(0,0,319,239,0,RGB(0,0,0));
TEXTOUT_P("SLIDER",137,90,2,RGB(255,0,0));
TEXTOUT_P("v1.0   2022",130,110,1,RGB(255,0,0));
TEXTOUT_P("by Tony Gallo",125,130,1,RGB(255,0,0));
wait(1.5);

//clear screen
RECT_P(0,0,319,239,0,RGB(255,255,255));

//credits
TEXTOUT_P("SLIDER",10,5,2,RGB(0,0,0));
TEXTOUT_P("v1.0   2022",100,6,1,RGB(0,0,0));
TEXTOUT_P("by Tony Gallo",250,5,1,RGB(0,0,0));

DrawBoard();
DrawScrambleButton();

done:= 0;
WHILE (done==0) DO


WHILE ISKEYDOWN(4)<>1 do

   touch:=mouse();

    if size(touch(1)) then
     if  touch(1,5)==0 then
             X:=B→R(touch(1,1));
             Y:=B→R(touch(1,2));

     if 20<=X<=220 and 25<=Y<=225 then
       //pressed board with finger

    i:=iquo((X-20),50);
          j:=iquo((Y-25),50);
          indx := 4*j + i + 1;

    if boardValues(indx) <> 16 then
      ProcessPress(indx);
    end;

  end;

  if 240<=X<=305 and 50<=Y<=65 then
  //pressed SCRAMBLE button
     ScrambleBoard();
  end;

   end;
   end;

     wait(.01);
     key:=-1;

     key:=getkey;

END;

if key==4 then
//pressed ESC to exit
  done:=1;
end;


END;
END;



ProcessPress(indx)
begin
   CASE

   if indx == 1 then
   //top left corner
  CASE
     if boardValues(indx+1) == 16 then
        MoveTile(indx,indx+1);
     end;

     if boardValues(indx+4) == 16 then
        MoveTile(indx,indx+4);
     end;
  END;
   end;

   if indx == 2 or indx == 3 then
   //top row
  CASE
     if boardValues(indx-1) == 16 then
        MoveTile(indx,indx-1);
     end;

     if boardValues(indx+1) == 16 then
        MoveTile(indx,indx+1);
     end;

     if boardValues(indx+4) == 16 then
        MoveTile(indx,indx+4);
     end;
  END;
   end;

   if indx == 4 then
   //top right corner
  CASE
     if boardValues(indx-1) == 16 then
        MoveTile(indx,indx-1);
     end;

     if boardValues(indx+4) == 16 then
        MoveTile(indx,indx+4);
     end;
  END;
   end;

   if indx == 5 or indx == 9 then
   //left side
  CASE
     if boardValues(indx-4) == 16 then
        MoveTile(indx,indx-4);
     end;

     if boardValues(indx+1) == 16 then
        MoveTile(indx,indx+1);
     end;

     if boardValues(indx+4) == 16 then
        MoveTile(indx,indx+4);
     end;
  END;
   end;

   if indx == 8 or indx == 12 then
   //right side
  CASE
     if boardValues(indx-4) == 16 then
        MoveTile(indx,indx-4);
     end;

     if boardValues(indx-1) == 16 then
        MoveTile(indx,indx-1);
     end;

     if boardValues(indx+4) == 16 then
        MoveTile(indx,indx+4);
     end;
  END;
   end;

   if indx == 13 then
   //bottom left corner
  CASE
     if boardValues(indx-4) == 16 then
        MoveTile(indx,indx-4);
     end;

     if boardValues(indx+1) == 16 then
        MoveTile(indx,indx+1);
     end;
  END;
   end;

   if indx == 14 or indx == 15 then
   //bottom row
  CASE
     if boardValues(indx-1) == 16 then
        MoveTile(indx,indx-1);
     end;

     if boardValues(indx+1) == 16 then
        MoveTile(indx,indx+1);
     end;

     if boardValues(indx-4) == 16 then
        MoveTile(indx,indx-4);
     end;
  END;
   end;

   if indx == 16 then
   //bottom right corner
  CASE
     if boardValues(indx-4) == 16 then
        MoveTile(indx,indx-4);
     end;

     if boardValues(indx-1) == 16 then
        MoveTile(indx,indx-1);
     end;
  END;
   end;

   if indx == 6 or indx == 7 or indx == 10 or indx == 11 then
   //middle
  CASE
     if boardValues(indx-4) == 16 then
        MoveTile(indx,indx-4);
     end;

     if boardValues(indx-1) == 16 then
        MoveTile(indx,indx-1);
     end;

     if boardValues(indx+1) == 16 then
        MoveTile(indx,indx+1);
     end;

     if boardValues(indx+4) == 16 then
        MoveTile(indx,indx+4);
     end;
  END;
   end;
   END;

CheckSolved();

end;


MoveTile(indx,blankindx)
begin
local val;

   val := boardValues(indx);
   FillSquare(blankindx, val);
   FillSquare(indx, 16);

end;


CheckSolved()
begin
local I;
local solved;

   solved := 1;
   FOR I FROM 1 to 16 DO  
	if boardValues(I) <> I then
		solved := 0;
	end;
   END;

   if solved == 1 then
	TEXTOUT_P("SOLVED",245,100,2,RGB(0,0,0));
   end;

   if solved == 0 then
	RECT_P(240,95,290,115,RGB(255,255,255),RGB(255,255,255));
   end;

   return solved;
end;

DrawBoard()
begin
local I;

  RECT_P(15,20,225,230,RGB(0,0,255),RGB(0,0,255));
//RECT_P(20,25,220,225,RGB(255,255,255),RGB(255,255,255));

//FOR I FROM 0 to 3 DO
//  LINE_P(20+50*I,25,20+50*I,225,RGB(0,0,255));
//  LINE_P(20,25+50*I,220,25+50*I,RGB(0,0,255));
//END;

   //scramble values then fill board

   boardValues := {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; //16 is the empty square

   ScrambleBoard();

   FillBoard();

end;


DrawScrambleButton()
begin
   RECT_P(240,50,305,65,0,RGB(0,255,0));
   TEXTOUT_P("SCRAMBLE",245,53,2,RGB(0,0,0));
end;


ScrambleBoard()
begin
local I;
local blankindx;
local solved;
local rnd;

   //locate empty square
   FOR I FROM 1 to 16 DO
      if boardValues(I) == 16 then
	blankindx := I;
      end;
   END;

   FOR I FROM 1 to 100 DO
   	if blankindx == 1 then
   	//top left corner
	   rnd := RANDINT(1,2);
               CASE
	      if rnd == 1 then
		  ProcessPress(blankindx+1);
		  blankindx := blankindx+1;
	      end;

	      if rnd == 2 then
		   ProcessPress(blankindx+4);
		   blankindx := blankindx+4;
	      end;
	    END;
	end;

	if blankindx == 2 or blankindx == 3 then
   	//top row
	   rnd := RANDINT(1,3);
               CASE
	       if rnd == 1 then
		   ProcessPress(blankindx-1);
		   blankindx := blankindx-1;
	       end;

	       if rnd == 2 then
		   ProcessPress(blankindx+1);
		   blankindx := blankindx+1;
	       end;
		
	       if rnd == 3 then
		   ProcessPress(blankindx+4);
		   blankindx := blankindx+4;
	       end;
	    END;
	 end;
   	
	if blankindx == 4 then
   	//top right corner
	   rnd := RANDINT(1,2);
               CASE
	      if rnd == 1 then
		  ProcessPress(blankindx-1);
		  blankindx := blankindx-1;
	      end;

	      if rnd == 2 then
		   ProcessPress(blankindx+4);
		   blankindx := blankindx+4;
	      end;
	    END;
	end;

	if blankindx == 5 or blankindx == 9 then
   	//left side
	   rnd := RANDINT(1,3);
               CASE
	       if rnd == 1 then
		   ProcessPress(blankindx-4);
		   blankindx := blankindx-4;
	       end;

	       if rnd == 2 then
		   ProcessPress(blankindx+1);
		   blankindx := blankindx+1;
	       end;
		
	       if rnd == 3 then
		   ProcessPress(blankindx+4);
		   blankindx := blankindx+4;
	       end;
	    END;
	 end;

	if blankindx == 8 or blankindx == 12 then
   	//right side
	   rnd := RANDINT(1,3);
               CASE
	       if rnd == 1 then
		   ProcessPress(blankindx-4);
		   blankindx := blankindx-4;
	       end;

	       if rnd == 2 then
		   ProcessPress(blankindx-1);
		   blankindx := blankindx-1;
	       end;
		
	       if rnd == 3 then
		   ProcessPress(blankindx+4);
		   blankindx := blankindx+4;
	       end;
	    END;
	 end;

   	if blankindx == 13 then
   	//bottom left corner
	   rnd := RANDINT(1,2);
               CASE
	      if rnd == 1 then
		  ProcessPress(blankindx-4);
		  blankindx := blankindx-4;
	      end;

	      if rnd == 2 then
		   ProcessPress(blankindx+1);
		   blankindx := blankindx+1;
	      end;
	    END;
	end;

	if blankindx == 14 or blankindx == 15 then
   	//bottom row
	   rnd := RANDINT(1,3);
               CASE
	       if rnd == 1 then
		   ProcessPress(blankindx-1);
		   blankindx := blankindx-1;
	       end;

	       if rnd == 2 then
		   ProcessPress(blankindx+1);
		   blankindx := blankindx+1;
	       end;
		
	       if rnd == 3 then
		   ProcessPress(blankindx-4);
		   blankindx := blankindx-4;
	       end;
	    END;
	 end;

   	if blankindx == 16 then
   	//bottom right corner
	   rnd := RANDINT(1,2);
               CASE
	      if rnd == 1 then
		  ProcessPress(blankindx-4);
		  blankindx := blankindx-4;
	      end;

	      if rnd == 2 then
		   ProcessPress(blankindx-1);
		   blankindx := blankindx-1;
	      end;
	    END;
	end;

	if blankindx == 6 or blankindx == 7 or blankindx == 10 or blankindx == 11 then
   	//middle
	   rnd := RANDINT(1,4);
               CASE
	       if rnd == 1 then
		   ProcessPress(blankindx-4);
		   blankindx := blankindx-4;
	       end;

	       if rnd == 2 then
		   ProcessPress(blankindx-1);
		   blankindx := blankindx-1;
	       end;
		
	       if rnd == 3 then
		   ProcessPress(blankindx+1);
		   blankindx := blankindx+1;
	       end;

	       if rnd == 4 then
		   ProcessPress(blankindx+4);
		   blankindx := blankindx+4;
	       end;
	    END;
	 end;

   END;

   //check to make sure the scramble didn't solve the puzzle
   solved := CheckSolved();

   if solved == 1 then
	ScrambleBoard();
   end;

end;


FillBoard()
begin
local I;

   FOR I FROM 1 to 16 DO
      FillSquare(I, boardValues(I));
   END;

end;


FillSquare(indx, val)
begin
local I,J;
local strval;
local strvallen,offset;

   I := irem(indx-1,4);
   J := iquo(indx-1,4);

   if val <> 16 then

     RECT_P(21+50*I,26+50*J,69+50*I,74+50*J,RGB(255,255,255),RGB(255,255,255));
     strval := IntToString(val);
     strvallen := size(strval);
 
     if strvallen == 1 then
        offset := 18;
     end;

     if strvallen == 2 then
        offset := 12;
     end;

     TEXTOUT_P(IntToString(val),21+50*I+offset,36+50*J,7,RGB(0,0,0));
   end;


   if val == 16 then
        //empty spot
        RECT_P(21+50*I,26+50*J,69+50*I,74+50*J,RGB(0,0,255),RGB(0,0,255));
   end;

   boardValues(indx) := val;
end;



IntToString(integer)
begin
local rem;
local string = "";
local negative = 0;

if integer == 0 then
   return "0";
end;

if integer < 0 then
   negative := 1;
  integer := integer * (-1);
end;

while integer > 0 do
  rem := irem(integer,10);
  string := DigitToChar(rem) + string ;
  integer := (integer - rem)/10;
end;

if negative == 1 then
  string:= "-" + string;
end;
return string;

end;


DigitToChar(digit)
begin

if digit == 0 then
  return "0";
end;

if digit == 1 then
  return "1";
end;

if digit == 2 then
  return "2";
end;

if digit == 3 then
  return "3";
end;

if digit == 4 then
  return "4";
end;

if digit == 5 then
  return "5";
end;

if digit == 6 then
  return "6";
end;

if digit == 7 then
  return "7";
end;

if digit == 8 then
  return "8";
end;

if digit == 9 then
  return "9";
end;

end;